﻿using System;
using System.Collections.Generic;
using System.Data.SqlTypes;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Security.Cryptography.Pkcs;
using System.Text;
using System.Threading.Tasks;

namespace FundHelper.Model
{
    // MultiPeriodCollection 类的实现
    internal abstract class MultiPeriodCollection<T> : IMultiPeriodCollection<T> where T : IndicatorResult
    {
        // 使用 Dictionary 来存储不同周期的 IndicatorCollection
        private readonly Dictionary<int, IndicatorCollection<T>> _periodCollections = new Dictionary<int, IndicatorCollection<T>>();
        public int PeriodCount = 0;
        // 添加指定周期的 IndicatorCollection
        public void AddIndicators(int period, IndicatorCollection<T> collection)
        {
            if (_periodCollections.ContainsKey(period))
            {
                throw new ArgumentException($"Indicators for period {period} already exist.");
            }

            _periodCollections[period] = collection;
            PeriodCount++;
        }

        // 获取指定周期的 IndicatorCollection
        public bool TryGetIndicators(int period,[MaybeNullWhen(false)]  out IndicatorCollection<T> collection)
        {
            return _periodCollections.TryGetValue(period, out collection);

        }
        protected abstract IndicatorCollection<T> CalPeriod(IEnumerable<ICanToTuple> his, int period);

        internal static MultiPeriodCollection<T> Create(IEnumerable<ICanToTuple> his, params int[] periods)
        {
            var multiCol = typeof(T) switch
            {
                var t when t == typeof(ZZLResult) => Activator.CreateInstance(typeof(ZZLResultCollection),true) as MultiPeriodCollection<T>,
                var t when t == typeof(BIASResult) => Activator.CreateInstance(typeof(BIASResultCollection), true) as MultiPeriodCollection<T>,


                _ => Activator.CreateInstance(typeof(ZZLResultCollection)) as MultiPeriodCollection<T>,
            };


            if (multiCol == null) throw new InvalidOperationException("Failed to create an instance of the specified type.");

            foreach (var period in periods)
            {
                if (his.Count() <= period)
                    throw new ArgumentException("无足够的数据计算");

                // 调用子类实现的 CalPeriod 方法
                var thePeriodResult = multiCol.CalPeriod(his, period);
                multiCol.AddIndicators(period, thePeriodResult);
            }

            return multiCol;
        }
    }
    internal interface IMultiPeriodCollection<T> where T :IndicatorResult
    {
        void AddIndicators(int period, IndicatorCollection<T> collection);
        bool TryGetIndicators(int period, [MaybeNullWhen(false)] out IndicatorCollection<T>? collection);
    }

    internal abstract class IndicatorCollection<T> where T : IndicatorResult
    {
        private readonly T[] _collection;
        protected virtual T[] Collection => _collection;
        public IndicatorCollection(IEnumerable<T> collection)
        {
            var co = collection.First().DateTime < collection.Last().DateTime
                ? collection.OrderByDescending(a => a.DateTime).ToArray()
                : collection.ToArray();
            _collection = co ?? throw new ArgumentNullException(nameof(collection));
        }

        public bool TryGet(int now, [MaybeNullWhen(false)] out T back)
        {
            if (now >= Collection.Length || now < 0)
            {
                back = default;
                return false;
            }

            back = _collection[now];
            return true;
        }
    }
    internal class LagCollection<T>(IEnumerable<T> collection): IndicatorCollection<T>(collection),ILagCollection<T> where T:IndicatorResult
    {
        public T ExtractLag(int now,int Lag)
        {
           if (now + Lag >= Collection.Length || now + Lag < 0)
                    throw new ArgumentOutOfRangeException($"{nameof(T)}数组越界了");
            return Collection[now+Lag];
        }
        public bool TryExtractLag(int now, int Lag, [MaybeNullWhen(false)] out T back)
        {
            if (now + Lag >= Collection.Length || now + Lag < 0)
            {
                back = null;
                return false;
            }
            back= Collection[now + Lag];
            return true;
        }
        public IEnumerable<T> ExtractLag(int now, params int[] Lags)
        {
            // 确保 Collection 已初始化并且 now 是有效的索引
            if (now < 0 || now+Lags.Max() >= Collection.Length)
                throw new ArgumentOutOfRangeException("Invalid parameters.");
            // 使用 List 来存储结果，避免多次调用 ElementAt
            List<T> back = new (Lags.Length);

            // 遍历 Lags 数组并过滤有效的 Lags
            foreach (var lag in Lags)
            {
                // 确保 lag 是有效的
                if (lag + now < Collection.Length)
                {
                    back.Add(Collection[now + lag]);
                }
            }
            return back;
        }

    }
    public interface ILagCollection<T> where T: IndicatorResult
    {
       T ExtractLag(int now,int Lag);
       IEnumerable<T> ExtractLag(int now, params int[] Lags);

    }


}
